<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
	<title>ZJCA客户端证书应用DEMO</title>
	
	<!--UI式样文件-->
	<link href="./style.css" rel="stylesheet" type="text/css">
	
    <!--ZJCA客户端相关的JS文件-->
	<script src="../../zjca_cmt/jquery.min.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_cert.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_key.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_com.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_npapi.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_websocket.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_def.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_err.js" type="text/javascript"></script>
</head>

<script type="text/javascript">

	/* ZJCA 客户端插件对象 */
	var g_ZjcaCMT = null;
	/* 当前枚举到的设备列表 */
	var g_UsingDeviceArray = null
	/* 当前使用的设备索引 */
	var g_UsingDeviceIndex = -1;
	/* 当前证书列表 */
	var g_UsingCertArray = null;	
	/* 当前显示的证书对象 */
	var g_SelCertObj = 0;
	/* 当前选择的签名结果格式(默认P1) */
	var g_SignType = 1;		
	/* 当前选择的密文结果格式(默认P1) */
	var g_CipherType = 1;	
	/* 当前选择的对称算法(默认DES_CBC)*/
	var g_SymmAlg = 0x04;	
	/* 当前选择的补齐方式(默认PKCS5)*/
	var g_PaddingType = 0x01;
	/* 随机数输出格式 */
	var g_RandromFormat = 0;

	/*
	 *	页面初始化
	 */
	window.onload = function() {
		//创建ZJCA客户端控件对象
		g_ZjcaCMT = new zjca_CMT(onCallbackKeyEvent, null);
		
		//设置客户端交互协议，在初始之前设置生效
		g_ZjcaCMT.setProtocol(PROTOCOL_HTTPS);
		
		//初始化ZJCA控件对象
		var resp = g_ZjcaCMT.init(ZJCA_PRODUCT_CMT, 1);
		if (resp.code != 0) {
			alert("初始化ZJCA客户端失败！\n错误信息：" + resp.msg);
		}else {
			//显示版本信息
			resp = g_ZjcaCMT.getVersion();
			if (resp.code == 0) {
				document.getElementById('txtInfo').innerHTML = "客户端版本：" + resp.res;
			}else {
				document.getElementById('txtInfo').innerHTML = "客户端版本：未知";
			}
			
			//获取设备列表
			resp = g_ZjcaCMT.getKeyList(false);
			if (resp.code != 0) {
				ShowErrorMessage("g_ZjcaCMT.getKeyList()失败！", resp.code);
			}else {
				FillDeviceList(resp.res);
			}
			
			//获取证书列表(所有介质内的所有证书)
			resp = g_ZjcaCMT.getCertList(-1, 0, 0);
			if (resp.code != 0) {
				ShowErrorMessage("g_ZjcaCMT.getCertList()失败！", resp.code);
			}else {
				g_UsingCertArray = resp.res;
			}
		}
	}
	/*
	 *	页面关闭
	 */
	window.onunload = function() {
		/* 释放接口 */
		if (g_ZjcaCMT) {
			g_ZjcaCMT.finaled();
		}
	}
	/*
	 *  列出设备
	 */
	function FillDeviceList(keyArray) {	
		// 删除老的选项
		var selKeyCtrl = document.getElementById('selKeys');
		var itemCount = selKeyCtrl.options.length;
		for (var n = 0; n < itemCount; n++) {
			selKeyCtrl.options.remove(0);
		}
		
		// 保存当前选择的设备
		var selDeviceSN;
		if (g_UsingDeviceIndex >= 0) {			
			selDeviceSN = g_UsingDeviceArray[g_UsingDeviceIndex].getSN();
		}	
		
		g_UsingDeviceArray = keyArray;		
		
		// 更新列表
		if (g_UsingDeviceArray && g_UsingDeviceArray.length > 0) {
			selKeyCtrl.options.add(new Option('请选择UKey设备', -1));

			for (var n = 0; n < g_UsingDeviceArray.length; n++) {
				var keySN = g_UsingDeviceArray[n].getSN();
				var keyLabel = g_UsingDeviceArray[n].getLabel();
				var text = keyLabel + "(" + keySN + ")";
				selKeyCtrl.options.add(new Option(text, n));
			}
		}
		else {
			selKeyCtrl.options.add(new Option('未发现任何ZJCA UKey设备', -1));
			document.form1.selKeys.options[0].selected = true;
			OnSelKeyChanged();
			return;
		}

		// 设置选中的设备
		var i = 0;
		if (g_UsingDeviceIndex >= 0) {
			for (i = 0; i < g_UsingDeviceArray.length; i++) {
				if (selDeviceSN == g_UsingDeviceArray[i].getSN()) {
					document.form1.selKeys.options[i].selected = true;
					g_UsingDeviceIndex = i;
					break;
				}
			}
		}
		if (i == g_UsingDeviceArray.length) {
			document.form1.selKeys.options[0].selected = true;
			OnSelKeyChanged();
		}
	}
	/*
	 *	设备事件响应函数
	 */	
	function onCallbackKeyEvent(type, index, name) {
		// 重新获取设备列表
		var resp = g_ZjcaCMT.getKeyList(false);	
		if (resp.code == 0) {
			FillDeviceList(resp.res);
		}	
			
		//获取证书列表(所有介质内的所有证书)
		resp = g_ZjcaCMT.getCertList(-1, 0, 0);
		if (resp.code == 0) {
			g_UsingCertArray = resp.res;
		}
	}
	/*
	 *	刷新设备列表
	 */
	function OnRefreshKey() {
		var resp = g_ZjcaCMT.getKeyList(true);	
		if (resp.code == 0) {
			FillDeviceList(resp.res);
		}	
			
		//获取证书列表(所有介质内的所有证书)
		resp = g_ZjcaCMT.getCertList(-1, 0, 0);
		if (resp.code == 0) {
			g_UsingCertArray = resp.res;
		}		
	}
	/*
	 *  选择设备，列出选中设备的基本信息
	 */
	function OnSelKeyChanged() {
		document.form1.txtSN.value = "";
		document.form1.txtLabel.value = "";
		
		g_UsingDeviceIndex = Number(document.getElementById("selKeys").value);			
		if (g_UsingDeviceIndex < 0 || g_UsingDeviceIndex >= g_UsingDeviceArray.length) {
			return;
		}
		document.form1.txtSN.value = g_UsingDeviceArray[g_UsingDeviceIndex].getSN();
		document.form1.txtLabel.value = g_UsingDeviceArray[g_UsingDeviceIndex].getLabel();	
	}
	/*
	 *	选择证书
	 */
	 function OnSelectCert(isSignCert) {
		var usage = isSignCert ? 1 : 2;
		
		if (g_UsingDeviceIndex == -1) {
			alert("请选择设备！");
			return;
		}
		if (!(g_UsingDeviceIndex >= 0 && g_UsingDeviceIndex < g_UsingDeviceArray.length)) {
			alert("设备不存在！");
			return;
		}
		
		var resp = g_ZjcaCMT.getCertContent(g_UsingDeviceIndex, 0,  usage);
		if (resp.code == 0) {
			var certBase64 = resp.res;
			document.form1.txtCert.value = certBase64;
			resp  = g_ZjcaCMT.decodeCert(certBase64); 
			ShowCertInfo(resp.res);
		}
		else {
			document.form1.txtCert.value = "no cert!";
			ShowErrorMessage("g_ZjcaCMT.getCertContent()失败！" , resp.code);
		}
	 }
	 /*
	  * 校验PIN码
	  */
	 function OnVerifyPin() {
		if (g_UsingDeviceIndex == -1) {
			alert("请选择设备！");
			return;
		}
		if (!(g_UsingDeviceIndex >= 0 && g_UsingDeviceIndex < g_UsingDeviceArray.length)) {
			alert("设备不存在！");
			return;
		}
		
		var resp  = g_ZjcaCMT.verifyPin(g_UsingDeviceIndex, ""); 
		if (resp.code == 0) {
			alert("校验PIN码成功！");
		}else {
			ShowErrorMessage("校验PIN码失败!", resp.code);
		}		
	 }
	 /*
	  *	修改PIN码
	  */
	 function OnChangePin() {
		if (g_UsingDeviceIndex == -1) {
			alert("请选择设备！");
			return;
		}
		if (!(g_UsingDeviceIndex >= 0 && g_UsingDeviceIndex < g_UsingDeviceArray.length)) {
			alert("设备不存在！");
			return;
		}
		
		var resp  = g_ZjcaCMT.changePin(g_UsingDeviceIndex, "", ""); 
		if (resp.code == 0) {
			alert("修改PIN码成功！");
		}else {
			ShowErrorMessage("修改PIN码失败!", resp.code);
		}	 
	 }
	 /*
	  *	解析证书(将证书内容以Base64格式输入) 
	  */
	function onParseCert(certBase64) {
		var resp  = g_ZjcaCMT.decodeCert(certBase64); 
		if (resp.code == 0) {
			ShowCertInfo(resp.res);
		}else {
			ShowErrorMessage("解码证书失败!", resp.code);
		}
	}
			
	/*
	 * 显示证书属性框
	 */
	function onShowCert(certBase64) {
		var resp = g_ZjcaCMT.showCert(certBase64, 0); 
		if (resp.code != 0) {
			ShowErrorMessage("显示证书失败!", resp.code);
		}
	}
	/*
	 *	验证证书
	 */
	 function onVerifyCert(certBase64) {
		var resp  = g_ZjcaCMT.verifyCert(certBase64, 0x01|0x02);
		if (resp.code == 0) {
			if (0 == resp.res) {
				alert("该证书有效!");
			}
			else if (1 == resp.res) {
				alert("该证书未生效!");
			}
			else if (2 == resp.res) {
				alert("该证书已失效!");
			}
			else if (4 == resp.res) {
				alert("该证书已被注销或作废!");
			}
			else if (8 == resp.res) {
				alert("该证书的签名无效!");
			}
			else if (16 == resp.res) {
				alert("该证书的颁发者非ZJCA!");
			}
			else if (32 == resp.res) {
				alert("该证书无可信任的根证书!");
			}
			else if (64 == resp.res) {
				alert("该证书的状态未知!");
			}
			else {
				alert("该证书无效，错误未知!");				
			}			
		}else {
			ShowErrorMessage("验证证书失败！", resp.code);			
		}
	 }	 
	/*
	 *	显示证书内容和信息
	 */
	function ShowCertInfo(certObj) {
		document.form1.selCertExtend.options[0].selected = true; 
		if (g_SelCertObj) {
			g_ZjcaCMT.releaseCert(g_SelCertObj);
			g_SelCertObj = 0;
		}
		
		if (certObj == null || certObj == 0 || certObj == undefined) {
			g_SelCertObj = 0;
			document.form1.txtCertSN.value = "";
			document.form1.txtCertCN.value = "";
			document.form1.txtCertDN.value = "";
			document.form1.txtCertTYPE.value = "";
			document.form1.txtBrNo.value = "";
			document.form1.txtSsNo.value = "";
			document.form1.txtOrgNo.value = "";
			document.form1.txtIDCardNo.value = "";				
			document.form1.txtValidFrom.value = "";
			document.form1.txtValidUntil.value = "";
			document.form1.txtKeyIntendUsage.value = "";
			document.form1.txtKeyIdentify.value = "";
			document.form1.txtCertStatus.value = "";
			document.form1.txtUSCCode.value = "";
		} else {
			g_SelCertObj = certObj;
			var certType = Number(g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_TYPE, "").res);
			var certUsage = Number(g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_USAGE, "").res);
			var validDate = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_VALIDDATE, "").res;
			var isRegisted = Number(g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_REGISTED, "").res);
			document.form1.txtCertSN.value = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_SN, "").res;
			document.form1.txtCertCN.value = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_SUBJECT, "CN=").res;
			document.form1.txtCertDN.value = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_SUBJECT, "").res;
			document.form1.txtCertTYPE.value = (certType == 1) ? "个人证书" : (certType == 2) ? "企业证书" : "未知";
			document.form1.txtBrNo.value = (certType != 1) ? g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_IC_CODE, "").res : "";
			document.form1.txtSsNo.value = (certType != 1) ? g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_SS_CODE, "").res : "";
			document.form1.txtOrgNo.value = (certType != 1) ? g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_ORG_CODE, "").res : "";					
			//document.form1.txtIDCardNo.value = (certType == 1) ? pCertificate.IDCardNo : "";			
			document.form1.txtIDCardNo.value = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_IDCARD, "").res;
			document.form1.txtValidFrom.value = validDate.fromDate;
			document.form1.txtValidUntil.value = validDate.endDate;
			document.form1.txtKeyIntendUsage.value = (certUsage==1) ? "签名" : "加密";
			document.form1.txtKeyIdentify.value = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_KEYID, "").res;
			document.form1.txtCertStatus.value = isRegisted == 1 ? "已注册" : "未注册";
			document.form1.txtUSCCode.value = g_ZjcaCMT.getCertAttribute(g_SelCertObj, FUNC_CERT_ATTRIBUTE_PARAM_USCCODE, "").res;
		}
		OnSelCertExtendChanged();		
		
	}
	/*
	 *	显示证书扩展项
	 */
	function OnSelCertExtendChanged() {
		var certExtObjID = "";
		var certExtText = "";
		var extIndex = document.getElementById("selCertExtend").value;
		switch(Number(extIndex)) {
		case 1:		// 基本约束
			certExtObjID = "2.5.29.19"; break;
		case 2:		// 增强型密钥用法
			certExtObjID = "2.5.29.37"; break;
		case 3:		// 密钥用法
			certExtObjID = "2.5.29.15"; break;
		case 4:		// 颁发机构密钥标识符
			certExtObjID = "2.5.29.35"; break;
		case 5:		// CRL 分发点
			certExtObjID = "2.5.29.31"; break;
		case 6:		// 颁发机构信息访问
			certExtObjID = "1.3.6.1.5.5.7.1.1"; break;
		case 7:		// 使用者密钥标识符
			certExtObjID = "2.5.29.14"; break;
		case 8:		// Netscape Cert Type
			certExtObjID = "2.16.840.1.113730.1.1"; break;
		case 9:		//个人身份证号
			certExtObjID = "1.2.156.10260.4.1.1"; break;
		case 10:	//社保号
			certExtObjID = "1.2.156.10260.4.1.2"; break;
		case 11:	//工商注册号
			certExtObjID = "1.2.156.10260.4.1.3"; break;
		case 12:	//组织机构代码
			certExtObjID = "1.2.156.10260.4.1.4"; break;
		case 13:	//税号
			certExtObjID = "1.2.156.10260.4.1.5"; break;
		case 14:	//系统用户名
			certExtObjID = "1.2.156.112573.14"; break;
		default:break;
		}
		
		if (certExtObjID != "") {
			var resp = g_ZjcaCMT.getCertExtension(g_SelCertObj, certExtObjID);
			if (resp.code == 0) {
				certExtText = resp.res;
			}
		}
		document.form1.txtCertExtend.value = certExtText;
	}	
	/*
	 *	打开原文文件
	 */
	 function on_OpenSrcFile() {
		var resp = g_ZjcaCMT.getFileName(1, "打开文件", "所有文件|*.*||");
		if (resp.code == 0) {			
			document.form1.txtFileName.value = resp.res;
		}
		else {
			document.form1.txtFileName.value = "";
			alert("选择文件失败！\n错误代码：", resp.code);
		}
	 }		 
	/*
	 *	打开密文文件
	 */
	 function on_OpenDesFile() {
		var resp = g_ZjcaCMT.getFileName(0, "保存文件", "");
		if (resp.code == 0) {			
			document.form1.txtDesFileName.value = resp.res;
		}
		else {
			document.form1.txtDesFileName.value = "";
			ShowErrorMessage("选择文件失败！", resp.code);
		}
	 }
	/*
	 *	打开解密后的文件
	 */
	 function on_OpenDecryptedFile() {
		var resp = g_ZjcaCMT.getFileName(0, "保存文件", "");
		if (resp.code == 0) {			
			document.form1.txtDecryptedFileName.value = resp.res;
		}
		else {
			document.form1.txtDecryptedFileName.value = "";
			ShowErrorMessage("选择文件失败！", resp.code);
		}		
	 }
	/*
	 *	选择签名格式
	 */
	function OnSelSignatureFormatChanged() {
		g_SignType = document.getElementById("selSignatureFormat").value;
	}	 
	/*
	 *	签名数据
	 */
	function on_btnSign() {
		var resp;
		
		if (g_UsingDeviceIndex == -1) {
			alert("请选择设备！");
			return;
		}
		if (!(g_UsingDeviceIndex >= 0 && g_UsingDeviceIndex < g_UsingCertArray.length)) {
			alert("设备不存在！");
			return;
		}
		
		if (document.form1.rdMessage.checked) {
			var data = document.form1.txtPlainText.value;
			
			resp = g_ZjcaCMT.signMessageUseKey(	g_UsingDeviceIndex,	//设备序号
												0,					//签名算法，不指定，使用默认的签名证书
												g_SignType, 		//签名格式
												0x07, 				//签名中附带的信息，P7格式的签名有效
												data				//待签名的数据
												);	
			/*									
			resp = g_ZjcaCMT.signDigestUseKey(	g_UsingDeviceIndex,	//设备序号
												0,					//签名算法，不指定，使用默认的签名证书
												g_SignType, 		//签名格式
												0x07, 				//签名中附带的信息，P7格式的签名有效
												data,				//待签名的数据
												0x4000);	*/
		} else if (document.form1.rdFile.checked) {
			var file = document.form1.txtFileName.value;
			if (file == "") {
				alert("请选择要签名的文件！");
				return;
			}
			resp = g_ZjcaCMT.signFileUseKey(g_UsingDeviceIndex, //设备序号
											0,					//签名算法，不指定，使用默认的签名证书
											g_SignType, 		//签名格式
											0x05, 				//签名中附带的信息，P7格式的签名有效
											file,				//待签名的文件名
											null,				//使用默认的UserId
											null				//使用同步模式
											);
		} else{
			alert("选择错误！");
			return;
		}		
		if (resp.code == 0) {
			document.form1.txtSignedData.value = resp.res;
		}
		else {
			document.form1.txtSignedData.value = "";
			if (0x81000007 != zjca_GetErrHexCode(resp.code)) { //如果不是用户取消操作,则显示错误信息
				ShowErrorMessage("签名失败！", resp.code);
			}
		}
	}	
	/*
	 *	显示签名数据的签名证书信息
	 */
	function on_btnShowSigInfo() {		
		var signature = document.form1.txtSignedData.value;
		var resp = g_ZjcaCMT.getSignatureAttached(signature);
		if (resp.code == 0) {
			var info;
			if (resp.res.text.length > 0) {
				info = "原文信息：";
				info += resp.res.text;
				info += "\n";
			}
			else {
				info = "签名中无原文！\n";
			}
			
			if (resp.res.cert.length > 0) {
				info += "签名中有证书！\n";
				document.form1.txtCert.value = resp.res.cert;
				onParseCert(resp.res.cert);
			}
			else {
				info += "签名中无证书！\n";		
			}
			
			if (resp.res.time.length > 0) {
				info += "签名时间：";
				info += resp.res.time;
				info += "\n";		
			}
			else {
				info += "签名中无时间戳！\n";			
			}
			alert(info);		
		}else {
			ShowErrorMessage("操作失败！", resp.code);			
		}
	}
	/*
	 *	验证签名
	 */
	function on_btnVerify() {
		var resp;
		// 验证消息的签名
		if (document.form1.rdMessage.checked) {	
			var base64Cert = document.form1.txtCert.value;
			var msg = document.form1.txtPlainText.value;
			var base64Sign = document.form1.txtSignedData.value;
			if (base64Cert == "") {
				alert("请输入验证签名的证书！");
				return;
			}
			if (base64Sign == "") {
				alert("请输入待验证的签名！");
				return;
			}
				
			// 验证签名
			resp = g_ZjcaCMT.verifyMessage(g_UsingDeviceIndex,	//如果为-1，则指定使用软件验签
										   msg,					//原文，当签名为P7且包含原文时，该参数可以为空。
									       base64Sign,			//签名
									       base64Cert			//证书，当签名为P7且包含证书时，该参数可以为空。
									       );
			/*resp = g_ZjcaCMT.verifyDigest(g_UsingDeviceIndex,	//如果为-1，则指定使用软件验签
										   msg,					//原文，当签名为P7且包含原文时，该参数可以为空。
										   0,
									       base64Sign,			//签名
									       base64Cert			//证书，当签名为P7且包含证书时，该参数可以为空。
									       );*/	
		}
		//	验证文件签名
		else {
			var base64Cert = document.form1.txtCert.value;
			var base64Sign = document.form1.txtSignedData.value;
			var file = document.form1.txtFileName.value;
			if (base64Cert == "") {
				alert("请输入验证签名的证书！");
				return;
			}
			if (base64Sign == "") {
				alert("请输入待验证的签名！");
				return;
			}
			if (file == "") {
				alert("请选择要验签的文件！");
				return;
			}
			// 验证签名
			resp = g_ZjcaCMT.verifyFile(g_UsingDeviceIndex, //如果为-1，则指定使用软件验签
								        file,				//原文文件名
								        base64Sign,		    //签名
								        base64Cert,			//证书，当签名为P7且包含证书时，该参数可以为空。
										null,				//使用默认的UserId
										null
								        );	
		}	
		if (resp.code == 0) {
			alert("签名验证成功！");
		}
		else {
			ShowErrorMessage("签名验证失败！", resp.code);			
		}
	}
	/*
	 *	选择密文封装格式
	 */
	function OnSelCipherFormatChanged() {
		g_CipherType = document.getElementById("selCipherFormat").value;			
	}		
	/*
	 *	选择对称算法
	 */
	function OnSelSymmAlgChanged() {
		g_SymmAlg = document.getElementById("selSymmAlg").value;		
	}		
	/*
	 *	选择对称算法补齐方式
	 */
	function OnSelPaddingTypeChanged() {
		g_PaddingType = document.getElementById("selPaddingType").value;					
	}
	/*
	 *	加密数据
	 */
	function on_btnEncrypt() {	
		var base64Cert;
		var key_index = -1;
		
		// 清空结果
		document.form1.txtCipherText.value = "";
					
		// 检查加密证书是否填写
		base64Cert = document.form1.txtCert.value;
		if (base64Cert == "") {
			alert("无加密证书！");
			return;
		}
		// 使用KEY加密
		if (document.form1.rdKeyEnc.checked) {
			// 检查KEY是否已经选择
			if (g_UsingDeviceIndex == -1) {
				alert("请选择设备！");
				return;
			}
			key_index = g_UsingDeviceIndex;
		}else { //使用软件加密
			key_index = -1;
		}
		
		var resp;
				
		// 对消息加密
		if (document.form1.rdMessage.checked) {	
			// 原文
			var plainText = document.form1.txtPlainText.value;
			
			// 密文保存到文件
			var desFile = null;
			if (!document.form1.ddMessage.checked) {
				desFile = document.form1.txtDesFileName.value;
				if (desFile == "") {
					alert("请选择要解密后的密文件！");
					return;
				}
			}
			
			// 加密消息
			resp = g_ZjcaCMT.encryptMessage(key_index, 				//-1表示使用软件加密
											base64Cert, 			//加密证书
											plainText, 				//明文消息
											g_SymmAlg,				//对称算法
											g_CipherType,  		    //密文封装类型
											g_PaddingType,			//对称加密补齐方式
											desFile					//密文文件名，为空则直接返回Base64格式的密文
											);
		}
		// 对文件加密
		else if (document.form1.rdFile.checked) {
			// 原文文件名
			var srcFile = document.form1.txtFileName.value;
			if (srcFile == "") {
				alert("请选择要加密的原始文件！");
				return;
			}
			
			// 密文保存到文件
			var desFile = null;
			if (!document.form1.ddMessage.checked) {
				desFile = document.form1.txtDesFileName.value;
				if (desFile == "") {
					alert("请选择要加密后的密文件！");
					return;
				}
			}
			
			// 加密文件
			resp = g_ZjcaCMT.encryptFile(key_index, 	//-1表示使用软件加密
								 base64Cert, 			//加密证书
								 srcFile, 				//明文文件名
								 desFile, 				//密文文件名，为空则直接返回Base64格式的密文
								 g_SymmAlg,				//对称算法
								 g_CipherType,  		//密文封装类型
								 g_PaddingType,			//对称加密补齐方式
								 null
								 );
		}
		if (resp.code == 0) {
			if (document.form1.ddMessage.checked) {	//Base64格式的密文
				document.form1.txtCipherText.value = resp.res;
			}else {	//密文文件名
				alert("加密成功！密文文件名为：" + resp.res);
			}
		}else {
			document.form1.txtCipherText.value = "";
			if (0x81000007 != zjca_GetErrHexCode(resp.code)) { //如果不是用户取消操作,则显示错误信息
				ShowErrorMessage("加密消息失败！", resp.code);
			}				
		}			
	}
	/*
	 *	解密数据
	*/
	function on_btnDecrypt() {
		// 检查KEY是否已经选择
		if (g_UsingDeviceIndex == -1) {
			alert("请选择设备！");
			return;
		}
		
		// 清空结果
		document.form1.txtDecryptedText.value = "";
		
		var resp;
		
		// 解密消息
		if (document.form1.ddMessage.checked) {
			// Base64格式的密文			
			var cipherText = document.form1.txtCipherText.value;
			if (cipherText == "") {
				alert("请输入待解密的密文！");
				return;
			}
			
			// 解密到文件
			var desFile = null;
			if (document.form1.decFile.checked) {
				desFile = document.form1.txtDecryptedFileName.value;
				if (desFile == "") {
					alert("请选择要解密后的密文件！");
					return;
				}
			}
			
			// 解密消息
			resp = g_ZjcaCMT.decryptMessageUseKey(	g_UsingDeviceIndex,	//Key的序号
													0,					//非对称算法，RSA:1, SM2:2, 未知:0
													g_SymmAlg,			//对称算法
													g_PaddingType,		//对称加密补齐方式
													cipherText,			//Base64格式的密文
													desFile				//解密后的文件名，为空则直接返回消息														
													);
		}
		// 解密文件
		else {			
			// 密文文件名
			var cipherFile = document.form1.txtDesFileName.value;
			if (cipherFile == "") {
				alert("请选择要解密的密文件！");
				return;
			}
			
			// 解密到文件
			var desFile = null;
			if (document.form1.decFile.checked) {
				desFile = document.form1.txtDecryptedFileName.value;
				if (desFile == "") {
					alert("请选择要解密后的密文件！");
					return;
				}
			}			
			
			// 解密文件
			resp = g_ZjcaCMT.decryptFileUseKey( g_UsingDeviceIndex,	//Key的序号
												0,					//非对称算法，RSA:1, SM2:2, 未知:0
												g_SymmAlg,			//对称算法
												g_PaddingType,		//对称加密补齐方式
												cipherFile,			//密文文件
												desFile,			//解密后的文件，为空则直接返回消息
												null
												);
		}
		if (resp.code == 0) {
			if (document.form1.decMessage.checked) {	//解密后的消息
				document.form1.txtDecryptedText.value = resp.res;
			}else {	//解密后的文件名
				alert("解密成功！解密结果文件名为：" + resp.res);
			}
		}else {
			document.form1.txtDecryptedText.value = "";
			if (0x81000007 != zjca_GetErrHexCode(resp.code)) { //如果不是用户取消操作,则显示错误信息
				ShowErrorMessage("解密消息失败！", resp.code);			
			}				
		}			
	}	
	/*
	 *	随机数格式选择	
	 */
	function OnSelRandRomChanged() {
		g_RandromFormat = document.getElementById("selRandromFormt").value;		
	}
	/*
	 *	选择随机数输出文件
	 */
	function OnSelRandFile() {
		var resp = g_ZjcaCMT.getFileName("保存文件", "");
		if (resp.code == 0) {			
			document.form1.txtRandFileName.value = resp.res;
		}
		else {
			document.form1.txtRandFileName.value = "";
			alert("选择文件失败！\n错误代码：" + resp.code);
		}
	}
	/*
	 *	生成随机数
	 */
	function OnTestRandrom() {
		// 检查KEY是否已经选择
		if (g_UsingDeviceIndex == -1) {
			alert("请选择设备！");
			return;
		}
		// 检查大小
		var size = document.form1.txtRandSize.value;
		if (Number(size) <= 0) {
			alert("输入的随机数大小有误！");
			return;
		}
		// 检查文件
		var randromFile = document.form1.txtRandFileName.value;
		if (randromFile == "") {
			alert("请选择保存随机数的文件！");
			return;
		}
		
		// 生成随机数
		var resp = g_ZjcaCMT.testRandrom(g_UsingDeviceIndex, size, g_RandromFormat, randromFile);
		if (resp.code == 0) {
			alert("随机数生成成功！");
		}else {
			alert("生成随机数失败！\n" + resp.code);
		}
	}
	

	//	显示错误信息函数
	function ShowErrorMessage(msg, code) {
		var errCode = zjca_GetErrHexCode(code);
		var errTxt = zjca_GetErrTxt(code);
	
		var errMsg = msg;
		errMsg += "\n";
		errMsg += "错误代码：";
		errMsg += errCode;
		errMsg += "\n";
		errMsg += "错误信息：";
		errMsg += errTxt;
		alert(errMsg);
	}
	/*
	*  show loading
	*/
	function show_loading(){
		var loading = document.getElementById("svg");
		loading.style.display = "block";
	}
	/*
	*  hide loading
	*/
	function hide_loading(){
		var loading = document.getElementById("svg");
		loading.style.display = "none";
	}
</script>

<body screen_capture_injected="true">
	<br>
	<br>
	<h2 align="center">ZJCA客户端证书应用DEMO</h2>
	<br>
	<br>
	<form name="form1" action="">
		<fieldset>
			<legend>客户端信息</legend>
			<table>
				<colgroup>
					<col class="col1">
					<col class="col2">
					<col class="col3">
				</colgroup><tbody>
					<tr>
						<td></td>
						<td></td>
						<td></td>
					</tr>
					<tr>
						<td><label name="txtInfo" id="txtInfo" width="500" >未检测到ZJCA客户端程序！</label></td>
					</tr>
				</tbody>
			</table>
		</fieldset>
		<br>
		<fieldset style="width:616px">
			<legend>密码设备</legend>
			<table>
				<colgroup>
					<col class="col1">
					<col class="col2">
					<col class="col3">
				</colgroup><tbody>
					<tr>
						<td></td>
						<td></td>
						<td></td>
					</tr>
					<tr>
						<td>请选择Key：</td>
						<td colspan="2"><select id="selKeys" name="selKeys" onchange="OnSelKeyChanged()"></select></td>
					<TD><INPUT name="btnRefresh" class="keyBtn" onclick="OnRefreshKey()" type="button" value="刷新"></TD>
					</tr>
				</tbody>
			</table>
		</fieldset>
		<br>
		<FIELDSET>		
			<LEGEND>Key Info</LEGEND>         
			<TABLE>
			<COLGROUP>
				<COL class="col1">
				<COL class="col2">
				<COL class="col3">
				<TBODY>
				<TR>
					<TD></TD>
					<TD></TD>
					<TD></TD>
				</TR>
				<TR>
					<TD>SN:                 </TD>
					<TD><INPUT name="txtSN" type="text" readonly="readonly"></TD>
					<TD><INPUT name="btnVerifyPin" class="keyBtn" onclick="OnVerifyPin()" type="button" value="检验PIN码"></TD>
				</TR>
				<TR>
					<TD>                    Label:                 </TD>
					<TD><INPUT name="txtLabel" type="text" readonly="readonly"></TD>
					<TD><INPUT name="btnChangePin" class="keyBtn" onclick="OnChangePin()" type="button" value="修改PIN码"></TD>
				</TR>
				<TR>
					<TD colspan="2"></TD>
					<TD><INPUT name="btnSignCert" class="keyBtn" onclick="OnSelectCert(true)" type="button" value="获取签名证书"></TD>
				</TR>
				<TR>
					<TD colspan="2"></TD>
					<TD><INPUT name="btnSignCert" class="keyBtn" onclick="OnSelectCert(false)" type="button" value="获取加密证书"></TD>
				</TR>
				</TBODY>
			</TABLE>
		</FIELDSET>
		<BR>
		<FIELDSET>
			<LEGEND>证书</LEGEND>
			<TEXTAREA name="txtCert" rows="5" cols="70"></TEXTAREA>
			<TABLE>
			<COLGROUP>
				<COL class="col1">
				<COL class="col2">
				<COL class="col3">
				<TBODY>
				<TR>
					<TD></TD>
					<TD></TD>
					<TD></TD>
				</TR>
				<TR>
					<TD>序列号（SN）：                 </TD>
					<TD><INPUT name="txtCertSN" type="text" readonly="readonly"></TD>
					<TD rowspan="2"><INPUT name="btnParseCert" onclick="onParseCert(document.form1.txtCert.value);" type="button" value="解析证书"></TD>
				</TR>
				<TR>
					<TD>通用名（CN）：                 </TD>
					<TD><INPUT name="txtCertCN" type="text" readonly="readonly"></TD>
				</TR>
				<TR>
					<TD>主题项（DN）：                 </TD>
					<TD><INPUT name="txtCertDN" type="text" readonly="readonly"></TD>
					<TD rowspan="2"><INPUT name="btnShowCert" onclick="onShowCert(document.form1.txtCert.value);" type="button" value="显示证书"></TD>
				</TR>
				<tr>
					<TD>证书类型：                    </TD>
					<TD><input name="txtCertTYPE" type="text" readonly="readonly"></TD>
				</tr>
				<tr>
					<td>工商注册号/社会信用代码：           </td>
					<td><input name="txtBrNo" type="text" readonly="readonly"></td>
					<TD rowspan="2"><INPUT name="btnVerifyCert" onclick="onVerifyCert(document.form1.txtCert.value);" type="button" value="验证证书"></TD>
				</tr>
				<tr>
					<td>组织机构代码：                      </td>
					<td>
						<input name="txtOrgNo" type="text" readonly="readonly"></td>
				</tr> 
				<tr>
					<td>社保号：                      </td>
					<td>
						<input name="txtSsNo" type="text" readonly="readonly"></td>
				</tr>  
				<tr>
					<td>身份证号：                    </td>
					<td>
						<input name="txtIDCardNo" type="text" readonly="readonly"></td>
				</tr>            
				<TR>
					<TD>有效期起始：                 </TD>
					<TD><INPUT name="txtValidFrom" type="text" readonly="readonly"></TD>
				</TR>
				<TR>
					<TD>有效期截止：                 </TD>
					<TD><INPUT name="txtValidUntil" type="text" readonly="readonly"></TD>
				</TR>
				<TR>
					<TD>密钥用法：                 </TD>
					<TD><INPUT name="txtKeyIntendUsage" type="text" readonly="readonly"></TD>
				</TR>
				<TR>
					<TD>密钥标识符：                 </TD>
					<TD><INPUT name="txtKeyIdentify" type="text" readonly="readonly"></TD>
				</TR>
				<TR>
					<TD>状态：             </TD>
					<TD><INPUT name="txtCertStatus" type="text" readonly="readonly"></TD>
				</TR>
				<TR>
					<TD>证书属性：             </TD>
					<TD><input name="txtUSCCode" type="text" readonly="readonly"></TD>
				</TR>           
				<TR>
					<TD>扩展项：             </TD>
					<TD >
						<SELECT name="selCertExtend" id = "selCertExtend" onchange="OnSelCertExtendChanged()" readonly="true" style="width:270px">
							<option value = 0>证书扩展项</Option>
							<option value = 1>基本约束</Option>
							<option value = 2>增强型密钥用法</Option>
							<option value = 3>密钥用法</Option>
							<option value = 4>颁发机构密钥标识符</Option>
							<option value = 5>CRL 分发点</Option>
							<option value = 6>颁发机构信息访问</Option>
							<option value = 7>使用者密钥标识符</Option>
							<option value = 8>Netscape Cert Type</Option>
							<option value = 9>个人身份证号</Option>
							<option value = 10>社保号</Option>
							<option value = 11>工商注册号</Option>
							<option value = 12>组织机构代码</Option>
							<option value = 13>税号</Option>
							<option value = 14>系统用户名</Option>
						</SELECT>
					</TD>
				</TR>          
				<TR>
					<TD>                     </TD>
					<TD><TEXTAREA name="txtCertExtend" rows="5" cols="31" readonly="true"></TEXTAREA></TD>
				</TR>          
				</TBODY>
			</TABLE>
		</FIELDSET>
		<BR>
		<FIELDSET>
			<LEGEND>签名/加解密</LEGEND>
			原文：         
			<TABLE>
				<TBODY>
				<TR>
					<TD>
						<INPUT name="MsgSource" id="rdMessage" type="radio" value="1" checked="1"><LABEL for="rdMessage">消息</LABEL>
					</TD>
					<TD>
						<TEXTAREA name="txtPlainText" rows="5" cols="60">测试原文。Test plain text. 1234567890~！@#￥%……&amp;*（）</TEXTAREA>
					</TD>
				</TR>
				<TR>
					<TD>
						<INPUT name="MsgSource" id="rdFile" type="radio" value="2"><LABEL for="rdFile">File</LABEL> 
					</TD>
					<TD>
						<INPUT name="txtFileName" type="text" readonly="readonly">
						<INPUT name="btnOpenSrcFile" onclick="on_OpenSrcFile();" type="button" value="打开文件">
					</TD>
				</TR>
				</TBODY>
			</TABLE>
			<HR>

			<TABLE>
				<COLGROUP>
				<COL class="col1">
				<COL class="col2">
				<COL class="col3">
				<TBODY>
				<TR>
					<TD>
					</TD>
					<TD>
					</TD>
					<TD>
					</TD>
				</TR>
				<TR>
					<TD style="vertical-align:top;">
						签名格式: 
					</TD>
					<TD style="vertical-align:top;">
						<SELECT id="selSignatureFormat" name="selSignatureFormat" onchange="OnSelSignatureFormatChanged()" readonly="true" style="width:200px;margin-left:-80px;">
							<option value = 1>PKCS#1</Option>
							<option value = 2>PKCS#7</Option>
							<option value = 3>RAW(仅限SM2)</Option>
							<option value = 4>DER(仅限SM2)</Option>
						</SELECT>
					</TD>
					<TD>
						<INPUT name="btnSign" class="keyBtn" onclick="on_btnSign();" type="button" value="Sign"><BR>
						<INPUT name="btnShowSigCert" class="certBtn" onclick="on_btnShowSigInfo();" type="button" value="显示签名证书信息"><BR>
						<INPUT name="btnVerify" class="certBtn" onclick="on_btnVerify();" type="button" value="Verify"> 
					</TD>
				</TR>
				</TBODY>
			</TABLE>
			签名结果:         
			<TEXTAREA name="txtSignedData" rows="5" cols="70"></TEXTAREA>
			<HR>

			<TABLE>
			  <COLGROUP>
			  <COL class="col1">
			  <COL class="col2">
			  <COL class="col3">
			  <TBODY>
			  <TR>
				<TD></TD>
				<TD></TD>
				<TD></TD></TR>
			  <TR>
				<TD colspan="2">
					<INPUT name="encCert" id="rdKeyEnc" type="radio" value="1" checked="1"><LABEL for="rdKeyEnc">使用Key加密</LABEL><BR>
					<INPUT name="encCert" id="rdCertEnc" type="radio" value="2"><LABEL for="rdCertEnc">使用外部证书加密（在上面证书框中设定证书）</LABEL>
				</TD>
				<TD>
					<INPUT name="btnEncrypt" class="keyBtn" onclick="on_btnEncrypt();" type="button" value="Encrypt"><BR>
					<INPUT name="btnDecrypt" class="keyBtn" onclick="on_btnDecrypt();" type="button" value="Decrypt">
				</TD>
			  </TR>
				<TD style="vertical-align:top;">
				密文格式: 
				<SELECT id="selCipherFormat" name="selCipherFormat" onchange="OnSelCipherFormatChanged()" readonly="true" style="width:76px;margin-left:0px;">
						<option value = 1>PKCS#1</Option>
						<option value = 2>PKCS#7(仅限RSA)</Option>
						<option value = 3>RAW(仅限SM2)</Option>
						<option value = 4>DER(仅限SM2)</Option>
					</SELECT>
				</TD>
				<TD style="vertical-align:top;">
					<div style="margin-left:125px">
						对称算法: 
						<SELECT id="selSymmAlg" name="selSymmAlg" onchange="OnSelSymmAlgChanged()" readonly="true" style="width:76px;">
							<option value = 0x4>DES_CBC(仅限RSA)</Option>
							<option value = 0x200>DES_ECB(仅限RSA)</Option>
							<option value = 0x8>3DES_CBC(仅限RSA)</Option>
							<option value = 0x400>3DES_ECB(仅限RSA)</Option>
							<option value = 0x10>SM1_ECB(仅限SM2)</Option>
							<option value = 0x4000>SM1_CBC(仅限SM2)</Option>
							<option value = 0x20>SM4_ECB(仅限SM2)</Option>
							<option value = 0x8000>SM4_CBC(仅限SM2)</Option>
						</SELECT>
					</div>
				</TD>
				<TD style="vertical-align:top;">					
					补齐方式: 
					<SELECT id="selPaddingType" name="selPaddingType" onchange="OnSelPaddingTypeChanged()" readonly="true" style="width:76px;margin-left:0px;">
						<option value = 1>PKCS5</Option>
						<option value = 0>不补齐</Option>
					</SELECT>
				</TD>
			  </TBODY>
			</TABLE>
			密文结果:         
			<!--<TEXTAREA name="txtCipherText" rows="5" cols="70"></TEXTAREA> -->       
			<TABLE>
				<TBODY>
				<TR>
					<TD>
						<INPUT name="MsgEncrypted" id="ddMessage" type="radio" value="1" checked="1"><LABEL for="ddMessage">消息</LABEL>
					</TD>
					<TD>
						<TEXTAREA name="txtCipherText" rows="5" cols="60"></TEXTAREA>
					</TD>
				</TR>
				<TR>
					<TD>
						<INPUT name="MsgEncrypted" id="ddFile" type="radio" value="2"><LABEL for="ddFile">File</LABEL> 
					</TD>
					<TD>
						<INPUT name="txtDesFileName" type="text" readonly="readonly">
						<INPUT name="btnSaveDesFile" onclick="on_OpenDesFile();" type="button" value="保存文件">
					</TD>
				</TR>
				</TBODY>
			</TABLE>
			<BR>
			解密结果:             
			<TABLE>
				<TBODY>
				<TR>
					<TD>
						<INPUT name="MsgDecrypted" id="decMessage" type="radio" value="1" checked="1"><LABEL for="decMessage">消息</LABEL>
					</TD>
					<TD>
						<TEXTAREA name="txtDecryptedText" rows="5" cols="60"></TEXTAREA>
					</TD>
				</TR>
				<TR>
					<TD>
						<INPUT name="MsgDecrypted" id="decFile" type="radio" value="2"><LABEL for="decFile">File</LABEL> 
					</TD>
					<TD>
						<INPUT name="txtDecryptedFileName" type="text" readonly="readonly">
						<INPUT name="btnDecryptedFile" onclick="on_OpenDecryptedFile();" type="button" value="保存文件">
					</TD>
				</TR>
				</TBODY>
			</TABLE>
		</FIELDSET>
		<BR>
		</FORM>
	</body>
</html>
